package com.gds.aspect;

import com.alibaba.fastjson.JSONObject;
import com.gds.utils.BizException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class LogAspect {

    private static Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // @Pointcut("@annotation(com.gds.aspect.LogInfo)")
    @Pointcut("execution(public* com.gds.controller..*.*(..))")
    public void logInfo() {

    }


    @Before("logInfo()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        String targetName = joinPoint.getTarget().getClass().getName();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        logger.info("................................");
        logger.info("请求方法:【" + targetName + "." + methodName + "】");
        if (method.isAnnotationPresent(LogInfo.class)) {
            LogInfo logInfo = method.getAnnotation(LogInfo.class);
            logger.info("接口描述:" + logInfo.operationDesc());
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        logger.info("请求路径" + request.getRequestURI());
        doMethmodParamLog(joinPoint);
    }


    @AfterReturning(returning = "ret", pointcut = "logInfo()")
    public void doAfterReturning(Object ret) throws Throwable {
        logger.info("请求返回data:" + JSONObject.toJSON(ret));
        logger.info(".................");
    }

    @AfterThrowing(throwing = "ex", pointcut = "logInfo()")
    public void doAfterThrowing(Throwable ex) {
        if (ex instanceof BizException) {
            BizException bizException = (BizException) ex;
            logger.info("请求业务异常返回:" + JSONObject.toJSON(bizException));
        } else {
            logger.info("异常:" + ex.getMessage());
        }
        logger.info(".................");
    }


    private void doMethmodParamLog(JoinPoint joinPoint) {
        // 参数值
        Object[] args = joinPoint.getArgs();
        // 参数名
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        if (args != null && argNames != null) {
            Map<String, Object> nameAndValue = new HashMap<>(5);
            for (int i = 0; i < argNames.length; i++) {
                if (!(args[i] instanceof HttpServletRequest)
                        && !(args[i] instanceof HttpServletResponse) && !(args[i] instanceof MultipartFile)) {
                    nameAndValue.put(argNames[i], JSONObject.toJSON(args[i]));
                }
            }
            logger.info("参数：-->" + nameAndValue);
        }
    }


}
